/**
 * Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
 * @brief FreeRTOS应用示例
 * @details
 * @author 王炸物联网https://blog.csdn.net/wangyx1234?spm=1000.2115.3001.5343
 * @date 2022
 * @version 1.0
 * @copyright 版权所有，禁止用于商业用途
 */
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"

#define TASK_TAG1      "TASK1"
#define TASK_TAG2      "TASK2"
#define TASK_TAG3      "TASK3"

TaskHandle_t task1; // 任务1结构对象
TaskHandle_t task2; // 任务2结构对象  
TaskHandle_t task3; // 任务3结构对象  

static int task1_flag;
static int task2_flag;
static int task3_flag;

#define BIT_REQUEST_FROM_TASK1  (1 << 0)
#define BIT_REQUEST_FROM_TASK2  (1 << 1)

static EventGroupHandle_t custom_event_group;

/**
 * 任务的运行代码
 * @param param 任务初始运行参数
 */
static void task1_process(void *arg)
{
    static const char *TASK1_TAG = TASK_TAG1;
    
    while (1) {
        xEventGroupSetBits(custom_event_group, BIT_REQUEST_FROM_TASK1);
        task1_flag++;
        if (task1_flag > 5) {
            vTaskSuspend(NULL);
        }
        vTaskDelay(pdMS_TO_TICKS(1500));
    }
}

/**
 * 任务的运行代码
 * @param param 任务初始运行参数
 */
static void task2_process(void *arg)
{
    static const char *TASK2_TAG = TASK_TAG2;
    
    while (1) {
        xEventGroupSetBits(custom_event_group, BIT_REQUEST_FROM_TASK2);
        task2_flag++;
        if (task2_flag > 5) {
            vTaskSuspend(NULL);
        }
        vTaskDelay(pdMS_TO_TICKS(1500));
    }
}

/**
 * 任务的运行代码
 * @param param 任务初始运行参数
 */
static void task3_process(void *arg)
{
    static const char *TASK3_TAG = TASK_TAG3;
    while (1) {
        EventBits_t bits = xEventGroupWaitBits(custom_event_group, BIT_REQUEST_FROM_TASK1 | 
        BIT_REQUEST_FROM_TASK2, pdTRUE, pdFALSE, portMAX_DELAY);

        printf("%s: wait events ok, now bits=0x%04x\r\n", TASK3_TAG, bits);

        task3_flag++;
    }
}

static void init(void) {
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());

    custom_event_group = xEventGroupCreate();

    if (custom_event_group == NULL) {
        printf("event froup creat fail\n");
    }
}

void app_main(void)
{
    init();
    /*
    static BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *constpcName, const uint32_t usStackDepth, 
    void *constpvParameters, UBaseType_t uxPriority, TaskHandle_t *constpxCreatedTask)*/
    xTaskCreate(&task1_process, "task1", 1024*2, (void *)"1", configMAX_PRIORITIES-2, &task1); // configMAX_PRIORITIES = 25
    xTaskCreate(&task2_process, "task2", 1024*2, (void *)"2", configMAX_PRIORITIES-2, &task2); // configMAX_PRIORITIES = 25
    xTaskCreate(&task3_process, "task3", 1024*2, (void *)"3", configMAX_PRIORITIES-1, &task3); // configMAX_PRIORITIES = 25
}
